#include "FunctionCallBuilder.h"

#include "ScriptCompiler/ScriptFileContext.h"

#include "ScriptCompiler/AST/FunctionCallNode.h"

#include "ScriptCompiler/ASTBuilder/ExpressionBuilder.h"
#include "ScriptCompiler/ASTBuilder/TypeBuilder.h"

#include "ScriptCompiler/ASTBuilder/ArgumentsBuilder.h"

CFunctionCallBuilder::CFunctionCallBuilder(std::shared_ptr<CScriptFileContext> InContext)
{
    Context = InContext;
    Result = std::make_shared<CFunctionCallNode>(InContext);
}

bool CFunctionCallBuilder::ReadCurentToken()
{
    //read function name
    {
        auto Token = Context->GetCurrentToken();
        if (Token->Type != EScriptTokenType::Identifier)
        {
            Context->RaiseError(10057,Token,U"Expected function name");
            return false;
        }
        Result->Name = Token;
        Context->CurrentTokenIndex++;
    }

    //read '<'
    {
        auto Token = Context->GetCurrentToken();
        if (Token->Type == EScriptTokenType::Less)
        {
            Context->CurrentTokenIndex++; //skip '<'

            //this is a generic function call
            Result->LeftAngleBracket = Token;
            while (true)
            {
                auto TypeBuilder = std::make_shared<CTypeBuilder>(Context);
                if (!TypeBuilder->ReadCurentToken())
                {
                    return false;
                }
                Result->GenericArguments.Add(TypeBuilder->Result);

                Token = Context->GetCurrentToken();
                if (Token->Type == EScriptTokenType::Greater)
                {
                    Result->RightAngleBracket = Token;
                    Context->CurrentTokenIndex++; //skip '>'
                    break;
                }
                else if (Token->Type == EScriptTokenType::Comma)
                {
                    Context->CurrentTokenIndex++; //skip ','
                    continue;
                }
                else
                {
                    Context->RaiseError(10058,Token,U"Expected ',' or '>'");
                    return false;
                }
            }
            
        }
    }

    //read arguments
    {
        auto ArgumentsBuilder = std::make_shared<CArgumentsBuilder>(Context);
        if (!ArgumentsBuilder->ReadCurentToken())
        {
            return false;
        }
        Result->Arguments = ArgumentsBuilder->Result;
    }

    return true;
}
